package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.*;
import com.itheima.service.DeptService;
import com.itheima.service.EmpExprService;
import com.itheima.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {

    @Autowired
    private DeptService deptService;

    @Autowired
    private EmpExprService empExprService;

    /**
     * 条件分页查询
     * @param param
     * @return
     */
    @Override
    public PageResult<Emp> getPageResult(EmpQueryParam param) {

        //  设置查询条件
        Page<Emp> page = Page.of(param.getPage(), param.getPageSize());
        //设置最后修改时间倒序排序
        page.addOrder(OrderItem.desc("update_time"));

        //使用lambda
        /**
         * LambdaQueryWrapper<Emp> 是 MyBatis Plus 提供的一种类型安全的查询条件构造器，用于构建 SQL 查询条件。
         * 它基于 Java Lambda 表达式语法，使你可以在不写 SQL 的情况下，通过链式调用方式动态拼接查询条件。
         */
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper<>(); // 创建查询条件对象
        queryWrapper.like(param.getName() != null && !param.getName().isEmpty(), Emp::getName, param.getName()) //模糊匹配
                .eq(param.getGender() != null, Emp::getGender, param.getGender())  //等值匹配
                .between(param.getBegin() != null && param.getEnd() != null, Emp::getEntryDate, param.getBegin(), param.getEnd()); //范围匹配
                // .page(page);

        //调用page方法完成分页查询
        page = page(page, queryWrapper);

        //分页条件查询员工数据
        List<Emp> empList = page.getRecords();
        log.info("查询结果：{}", empList); // 打印查询结果

        //查询部门数据
        //手机员工所属的部门id，放到set集合中 -- 不重复
        //map() 的作用就是：把集合里的每一个元素按照你的规则变个样子。 collect(Collectors.toSet()) 的作用是：把流里的所有元素收集成一个 Set 集合，并自动去重。
        //从所有员工中提取出他们各自的部门 ID，并把这些 ID 放进一个不重复的集合里（即：找出所有不同的部门 ID）。
        Set<Integer> deptIds = empList.stream().map(Emp::getDeptId).collect(Collectors.toSet());

        //根据id查询部门
        if (!deptIds.isEmpty()) {
            List<Dept> depts = deptService.listByIds(deptIds); //  根据部门 ID 批量查询部门数据

            //封装结果返回 把部门名称设置到员工数据中
        /*  empList.forEach(emp -> {
            depts.forEach(dept -> {
                if (emp.getDeptId() != null && emp.getDeptId().equals(dept.getId())) {
                    emp.setDeptName(dept.getName());
                }
            });
        });
      }*/
            //将部门数据封装成Map<deptId, name>
            Map<Integer, String> deptMap = depts.stream().collect(Collectors.toMap(Dept::getId, Dept::getName));
            empList.forEach(emp -> {
                emp.setDeptName(deptMap.getOrDefault(emp.getDeptId(), null));
                /**
                 * 从 deptMap 这个 Map 中，根据当前员工的部门 ID（emp.getDeptId()）查找对应的部门名称。
                 * 如果找到了，就把部门名称设置给员工对象；
                 * 如果没找到对应的部门 ID（比如数据异常或为空），就设置为 null。
                 */
            });
        }
        return new PageResult<>(page.getTotal(), empList);
    }

    /**
     * 保存员工信息
     * @param emp
     */
    @Override
    @Transactional
    public void saveEmp(Emp emp) {
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        save(emp);

        //保存员工工作经历
        List<EmpExpr> exprList = emp.getExprList(); // 获取员工工作经历列表
        if (!exprList.isEmpty()) {  // 判断工作经历列表是否为空
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId()); //  设置员工id
                empExprService.saveBatch(exprList); //  批量保存员工工作经历
            });
        }
    }

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @Override
    public Emp getEmpById(Integer id) {
        Emp emp = getById(id); //  查询员工信息
        //通过 empExprService 使用 Lambda 查询链，筛选出 empId 等于传入 id 的所有工作经历记录，并封装到 emp 对象中。
        //调用 .list() 执行查询并返回员工的工作经历列表。
        List<EmpExpr> empExprList = empExprService.lambdaQuery().eq(EmpExpr::getEmpId, id).list(); //  查询员工工作经历

        //  封装员工工作经历
        emp.setExprList(empExprList);
        return emp; // 返回员工信息
    }

    /**
     * 修改员工信息
     * @param emp
     */
    @Override
    @Transactional
    public void updateEmp(Emp emp) {
        //1.修改员工基本信息
        emp.setUpdateTime(LocalDateTime.now());
        updateById(emp);
        //2.先删除员工工作经历
        empExprService.remove(new LambdaQueryWrapper<EmpExpr>().eq(EmpExpr::getEmpId, emp.getId()));

        //3.保存员工工作经历
        List<EmpExpr> exprList = emp.getExprList(); // 获取员工工作经历列表
        if (!exprList.isEmpty()) {
            exprList.forEach(expr -> {
                expr.setEmpId(emp.getId()); //  设置员工id
                empExprService.saveBatch(exprList); //  批量保存员工工作经历
            });
        }
    }

    @Override
    public void removeEmpsByIds(List<Integer> ids) {
        //删除员工信息
        removeByIds(ids);

        // 根据员工id批量删除员工工作经历
        //构建查询条件，筛选出 emp_id 在指定列表中的工作经历记录
        empExprService.remove(new LambdaQueryWrapper<EmpExpr>().in(EmpExpr::getEmpId, ids));
        /**
         * 1. LambdaQueryWrapper<EmpExpr>
         * 这是 MyBatis Plus 提供的类型安全查询构造器。
         * <EmpExpr> 表示操作的是 EmpExpr 实体类对应的数据库表。
         * 使用 LambdaQueryWrapper 可以通过方法引用（如 EmpExpr::getEmpId）来指定字段，避免硬编码字段名，提高可读性和安全性。
         */
    }
}
